﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using EasyModbus;
using Microsoft.Extensions.Logging;
using XY_PLC;
namespace can.Achieve
{
    internal static class Helpers
    {
        internal static async Task WaitFor<T>(
            this T source,
            Func<T, bool> check,
            int Millisecond,
            string title = ""
        )
        {
            if (check == null)
            {
                throw new ArgumentNullException(nameof(check));
            }

            using var tokenSource = new CancellationTokenSource(Millisecond);

            var timeToken = tokenSource.Token;

            while (!check(source))
            {
                await Task.Delay(50, timeToken).ConfigureAwait(false);
            }
        }

        internal static byte[] Str2AddressNo(this string addressNo)
        {
            var tempSpan = addressNo.AsSpan();
            var data = new byte[addressNo.Length / 2];
            for (int i = 0; i < data.Length; i++)
            {
                data[i] = Convert.ToByte(tempSpan.Slice(i * 2, 2).ToString(), 16);
            }

            return data;
        }

        internal static float ParseFloat(int[] registers, ModbusStorageOrder storageOrder)
        {
            if (registers.Length < 2)
                throw new ArgumentException(
                    "At least two registers are required for a float value."
                );

            // 转换 int[] 为 byte[]，并按存储顺序解析
            byte[] bytes = new byte[4];
            switch (storageOrder)
            {
                case ModbusStorageOrder.BigEndian:
                    // 标准大端序：高寄存器先于低寄存器
                    bytes[0] = (byte)(registers[0] >> 8); // 高寄存器高字节
                    bytes[1] = (byte)(registers[0] & 0xFF); // 高寄存器低字节
                    bytes[2] = (byte)(registers[1] >> 8); // 低寄存器高字节
                    bytes[3] = (byte)(registers[1] & 0xFF); // 低寄存器低字节
                    break;

                case ModbusStorageOrder.LittleEndian:
                    // 小端序：高寄存器先于低寄存器，但字节低位在前
                    bytes[1] = (byte)(registers[0] >> 8); // 高寄存器高字节
                    bytes[0] = (byte)(registers[0] & 0xFF); // 高寄存器低字节
                    bytes[3] = (byte)(registers[1] >> 8); // 低寄存器高字节
                    bytes[2] = (byte)(registers[1] & 0xFF); // 低寄存器低字节
                    break;

                case ModbusStorageOrder.WordSwap:
                    // 低寄存器先于高寄存器
                    bytes[0] = (byte)(registers[1] >> 8); // 低寄存器高字节
                    bytes[1] = (byte)(registers[1] & 0xFF); // 低寄存器低字节
                    bytes[2] = (byte)(registers[0] >> 8); // 高寄存器高字节
                    bytes[3] = (byte)(registers[0] & 0xFF); // 高寄存器低字节
                    break;

                case ModbusStorageOrder.FullSwap:
                    // 低寄存器先于高寄存器，且字节顺序为低字节在前
                    bytes[1] = (byte)(registers[1] >> 8); // 低寄存器高字节
                    bytes[0] = (byte)(registers[1] & 0xFF); // 低寄存器低字节
                    bytes[3] = (byte)(registers[0] >> 8); // 高寄存器高字节
                    bytes[2] = (byte)(registers[0] & 0xFF); // 高寄存器低字节
                    break;

                default:
                    throw new ArgumentException("Unsupported storage order");
            }

            return BitConverter.ToSingle(bytes, 0);
        }
    }

    internal enum ModbusStorageOrder
    {
        BigEndian,
        LittleEndian,
        WordSwap,
        FullSwap
    }
}
